package com.datoucai.config;

import com.alibaba.cloud.nacos.annotation.NacosConfigKeysListener;
import com.alibaba.nacos.api.config.ConfigChangeEvent;
import com.alibaba.nacos.api.config.ConfigChangeItem;
import com.alibaba.nacos.api.config.annotation.NacosConfigListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Component
public class DynamicThreadPoolConfig {

    @NacosConfigListener(dataId = "dtc-comment-all-env.yaml")
    public void onConfigChange(String newConfig) {
        try {
            log.debug("Nacos配置变更触发，内容长度：{}", newConfig.length());
            log.info("配置内容：{}", newConfig);
        } catch (Exception e) {
            log.error("处理Nacos配置变更异常", e);
        }
    }
    // 监听指定配置的变更事件
    @NacosConfigKeysListener(dataId = "dtc-comment-all-env.yaml",group="DEFAULT_GROUP")
    public void onConfigChange(ConfigChangeEvent event) {
        // 遍历所有变更的键
        for (ConfigChangeItem item : event.getChangeItems()) {
            String oldValue = item.getOldValue();  // 旧值
            String newValue = item.getNewValue();  // 新值
            String type = item.getType().name();   // 变更类型（ADDED/MODIFIED/DELETED）
            log.info("配置项 {} 变更：旧值={}, 新值={}, 类型={}", item, oldValue, newValue, type);
        }
    }
    @Bean
    @RefreshScope
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(ThreadPoolProperties properties) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        checkThreadPoolCoreParamAndCorrect(properties);
        executor.setCorePoolSize(properties.getCoreSize());
        executor.setMaxPoolSize(properties.getMaxSize());
        executor.setQueueCapacity(properties.getQueueCapacity());
        executor.setKeepAliveSeconds(properties.getKeepAliveTime());
        executor.setThreadFactory(new DynamicThreadFactory("dynamic-pool"));
        executor.setRejectedExecutionHandler(getRejectedExecutionHandler(properties.getRejectedExecutionHandler()));
        executor.setWaitForTasksToCompleteOnShutdown(properties.isWaitForJobsToCompleteOnShutdown());
        executor.setAwaitTerminationSeconds(properties.getAwaitTerminationSeconds());
        executor.initialize();
        log.info("动态线程池-核心参数是: coreSize={}, maxSize={}, " +
                        "queueCapacity={}, keepAliveSeconds={}秒, rejectedExecutionHandler={}" +
                        ", waitForJobsToCompleteOnShutdown={}, awaitTerminationSeconds={}",
                properties.getCoreSize(),properties.getMaxSize(),
                properties.getQueueCapacity(),properties.getKeepAliveTime(),
                properties.getRejectedExecutionHandler(),
                properties.isWaitForJobsToCompleteOnShutdown(),properties.getAwaitTerminationSeconds()
        );
        return executor;
    }

    /**
     * 检查线程池核心参数是否有误，如果有误并纠正
     * @param properties
     */
    private void checkThreadPoolCoreParamAndCorrect(ThreadPoolProperties properties) {
        if(properties.getCoreSize() < 0 ||
                properties.getMaxSize() <= 0 ||
                properties.getMaxSize() < properties.getCoreSize() ||
                properties.getKeepAliveTime() < 0){
            log.warn("动态线程池核心参数配置有误,请立即检查并重新配置");
            properties.setCoreSize(properties.getMaxSize());
            properties.setMaxSize(properties.getMaxSize());
            properties.setQueueCapacity(properties.getQueueCapacity());
            properties.setKeepAliveTime(properties.getKeepAliveTime());
            properties.setRejectedExecutionHandler(properties.getRejectedExecutionHandler());
        }
    }


    /**
     * 根据给定的名称返回相应的拒绝执行策略。
     *
     * @param rejectedExecutionHandlerName 拒绝执行策略的名称，支持的策略包括 "AbortPolicy", "CallerRunsPolicy", "DiscardOldestPolicy", "DiscardPolicy"。
     * @return 返回一个 {@link RejectedExecutionHandler} 实例，根据传入的名称选择不同的策略。
     *         - "AbortPolicy": 抛出 {@link RejectedExecutionException} 中断任务提交。
     *         - "CallerRunsPolicy": 由调用线程（通常是主线程）执行被拒绝的任务。
     *         - "DiscardOldestPolicy": 丢弃等待队列中最旧的任务后重试提交。
     *         - "DiscardPolicy": 静默丢弃被拒绝的任务。
     *         - 其他名称: 返回自定义的拒绝执行策略 {@link CustomRejectedExecutionHandler}。
     */
    public RejectedExecutionHandler getRejectedExecutionHandler(String rejectedExecutionHandlerName) {
        if("AbortPolicy".equalsIgnoreCase(rejectedExecutionHandlerName)) {
            // 抛异常中断流程
            return new ThreadPoolExecutor.AbortPolicy();
        } else if("CallerRunsPolicy".equalsIgnoreCase(rejectedExecutionHandlerName)){
            // 调用主线程执行任务
            return new ThreadPoolExecutor.CallerRunsPolicy();
        } else if("DiscardOldestPolicy".equalsIgnoreCase(rejectedExecutionHandlerName)){
            // 丢弃旧任务后重试
            return new ThreadPoolExecutor.DiscardOldestPolicy();
        } else if("DiscardPolicy".equalsIgnoreCase(rejectedExecutionHandlerName)){
            // 静默丢弃
            return new ThreadPoolExecutor.DiscardPolicy();
        } else {
            // 自定义拒绝策略
            return new CustomRejectedExecutionHandler();
        }
    }


}
